package com.xpec.c4.service.common;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.xpec.c4.codec.CodecUtility;
import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.message.ConstantCode;
import com.xpec.c4.message.MessageTypes;
import com.xpec.c4.service.contexts.Contexts;
import com.xpec.c4.service.contexts.ScopeType;
import com.xpec.c4.service.exceptions.MessageException;
import com.xpec.c4.service.ioc.IocContainer;
import com.xpec.c4.service.message.MessageAction;
import com.xpec.c4.service.message.NetMessage;

/**
 * 消息处理类
 * 
 * @author lipeilin
 * 
 */
public class ClientMessageHandle {

	/**
	 * Log管理器
	 */
	private static final Log log = LogFactory.getLog(ClientMessageHandle.class);
	
	/**
	 * 模块的映射
	 */
	private ModuleInfo moduleInfo = new ModuleInfo();

	/**
	 * 处理消息请求
	 * 
	 * @param messageType
	 * @param messageContent
	 * @param sessionID
	 * @return
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public Object handleMessage(int messageType, byte[] messageContentBytes, GUID sessionID, String moduleID,String srcService) 
		throws IllegalAccessException, InvocationTargetException 
	{

		// 注入moduleID
		Contexts.putInContexts("moduleID", moduleID);
		Contexts.putInContexts("srcService", srcService);
		Object result = null;
		try {
			result = handleMessage(messageType, messageContentBytes, sessionID);
		} catch (RuntimeException e) {
			log.error("handleMessage error! sessionID:"+sessionID+" moduleID:"+moduleID+" messageType:"+messageType,e);
			throw e;
		}

		return result;
	}

	/**
	 * 处理消息请求
	 * 
	 * @param messageType
	 * @param messageContent
	 * @param sessionID
	 * @return
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 * 
	 * @author lipeilin
	 * @2011-3-11 下午12:16:31
	 */
	public Object handleMessage(int messageType, byte[] messageContentBytes, GUID sessionID) 
		throws IllegalAccessException, InvocationTargetException 
	{
		// 处理方法
		Method dealAction = moduleInfo.getDealMethod(messageType);

		// 处理类
		Class<?> dealClass = moduleInfo.getDealClazz(messageType);
		
		if (dealClass == null) 
		{
			log.warn(ConstantCode.getName(MessageTypes.class, messageType) + " " + messageType
					+ " not mapping deal action!!!");
			return null;
		}
		
		Object messageContent = null;
		try {
			messageContent = CodecUtility.decodeByte(messageContentBytes);
		} catch (RuntimeException e1) {
			log.error("can not decode msg! messageType:" + messageType
					+ " sessionID:"+sessionID + " actionClass:" + dealClass);
			throw e1;
		}

		if (sessionID != null) 
		{
			Contexts.putSessionIDInEventContext(sessionID);
			Contexts.flushSessionIDUserID();
			Contexts.putInContexts("sessionID", sessionID, ScopeType.EVENT);
		}

		// 方法前运行
		
		Object dealObj = IocContainer.createObject(dealClass);

		Object obj = null;
		try 
		{
			// 有sessionID，就做同步
			//if (sessionID != null) 
			//{
			//	synchronized (sessionID) 
			//	{
			//		obj = dealAction.invoke(dealObj, messageContent);
			//	}
			//}
			//else// 没有的话，可能是其他服务节点过来的，不同步 
			//{
			messageContent=CodecUtility.h2oArrayTransfer(messageContentBytes, messageContent, dealAction.getParameterTypes());
			obj = dealAction.invoke(dealObj, messageContent);
			//}
		} catch (IllegalArgumentException e) {
			log.error("sessionID:" + sessionID + " message type:" + messageType
					+ " \tmessage object:" + messageContent
					+ " \tmessage method:" + dealAction, e);
			throw e;
		} catch (RuntimeException e) {
			log.error("sessionID:" + sessionID + " message type:" + messageType
					+ " \tmessage object:" + messageContent
					+ " \tmessage method:" + dealAction, e);
			throw e;
		}

		// 返回消息

		if (obj == null) // 不返回对象，或返回是null，则不作任何处理。
		{

		}
		else if (obj instanceof NetMessage) // 返回的对象是NetMessage，用于发送一个指定客户端对象
		{
			// 如果sessionID是空，则表示返回原来的session
			if (((NetMessage) obj).getSessionID() == null) 
			{
				((NetMessage) obj).setSessionID(sessionID);
			}
			MessageAction.sendMessage((NetMessage) obj);
		}
		else if (obj instanceof Collection) // 返回的对象是Collection<NetMessage>，用于发送多个对象 
		{
			MessageAction.sendMessage((Collection<NetMessage>) obj);
		}
		else // 如果是其他类型对象，则无法处理，抛错
		{
			throw new MessageException("return message is not NetMessage:"
					+ obj);
		}

		// 清除event context
		Contexts.destroyEventContext();
		return obj;
	}

	public ModuleInfo getModuleInfo() {
		return moduleInfo;
	}

	public void setModuleInfo(ModuleInfo moduleInfo) {
		this.moduleInfo = moduleInfo;
	}

}
